﻿using StarryEdge.Core.Device;
using StarryEdge.Core.Models;
using StarryEdge.Core;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StarryEdge.Devices.MeterDevice.ScanCode
{
    public class Seuic_X4LD3 : NormalDeviceBase, IDeviceInteraction<int>
    {
        private byte[] _start = Encoding.ASCII.GetBytes("LON");
        private byte[] _end = Encoding.ASCII.GetBytes("LOFF");
        public Seuic_X4LD3(ICommunication com, IStarryEdgeLog edgeLog, Func<DeviceInfoModel, IDevice, bool> func) : base(com, edgeLog, func)
        {
        }

        public void Close() => _com.Close();

        public bool Open() => _com.Open();

        public TValue ReadSingle<TValue>(int address, int length = 3)
        {
            Stopwatch stopwatch = Stopwatch.StartNew();
            List<byte> barcode_bytes = new List<byte>();
            int count = 0;
            for (int i = 0; i < length; i++)
            {
                try
                {
                    barcode_bytes.Clear();
                    var bl = _com.Send(_start);
                    if (bl)
                    {
                        barcode_bytes.AddRange(_com.Receive());
                        count = barcode_bytes.Count;
                        stopwatch.Restart();
                        while (count < 2 || barcode_bytes[count - 2] != 0x0D || barcode_bytes[count - 1] != 0x0A)
                        {
                            Thread.Sleep(10);
                            barcode_bytes.AddRange(_com.Receive());
                            if (stopwatch.ElapsedMilliseconds > 2000)
                            {
                                return default;
                            }
                        }
                        string barcode = Encoding.ASCII.GetString(barcode_bytes.ToArray());
                        _com.Send(_end);
                        if (barcode != null && barcode.Contains("\r\n"))
                        {
                            return (TValue)(object)barcode.Split("\r\n")[0];
                        }
                        return (TValue)(object)barcode;
                    }
                    return default;
                }
                catch (Exception)
                {
                    Thread.Sleep(100);
                    if (_func.Invoke(_com.DeviceInfo, this))
                    {
                        return default;
                    }
                }
            }
            return default;
        }

        public bool WriteSingle(int address, object value, int length)
        {
            return _com.Send(_start);
        }
    }
}
